package com.sdy.sd;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.RectF;
import android.graphics.Region;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.util.Log;
import android.util.TypedValue;
import android.view.View;

import androidx.annotation.Nullable;

class Polor {
    double r;
    double theta;
};

public class artPixView extends View {
    static final int PADDING_DP = 10;
    static Bitmap mBmp = null;
    private static final String TAG = "artPixView";

    public artPixView(Context context, @Nullable AttributeSet attrs) {super(context, attrs);}

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);

        int miner = Math.min(FullscreenActivity.mDm.widthPixels, FullscreenActivity.mDm.heightPixels) / 2 - (int)dp2pix(PADDING_DP);
        //setMeasuredDimension(miner, (int)(miner * 0.4));
        setMeasuredDimension(miner, miner);
    }

    float dp2pix(float dpSize) {
        DisplayMetrics dm = getResources().getDisplayMetrics() ;
        return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dpSize, dm);
    }

    static public double log(double value, double base) {
        return Math.log(value) / Math.log(base);
    }
    private static int getValByPattern(int pattern, double dx, double fullX) {
        if(1 == (pattern & 0x1)) dx = fullX - dx;

        if(0 == pattern || 1 == pattern) {
            return (int)(dx * 255 / fullX);
        }
        if(2 == pattern || 3 == pattern) {
            double v1 = (dx * Math.PI / fullX); //[0, pi]
            double v2 = Math.cos(v1); //[-1, 1]
            double sinv0_2 = v2 + 1; //[0, 2]
            return (int)(255 * sinv0_2 / 2);
        }
        if(4 == pattern || 5 == pattern) {
            double t0_2pi = (dx * 2 * Math.PI / fullX);
            double sc_sum = Math.sin(t0_2pi) + Math.cos(t0_2pi); //(-1.5, 1.5)
            double sinv0_2 = sc_sum + 1.5; //(0, 3)
            return (int)(255 * sinv0_2 / 3);
        }
        if(6 == pattern || 7 == pattern) {
            double v1 = dx / fullX;
            if(v1 > 0.99) v1 = 0.99;
            double v2 = 1d - Math.pow(v1, 2 / 3d);
            double v3 = log(v2, 2 / 3d) / 12.5;
            return (int)(255 * v3);
        }
        if(8 == pattern || 9 == pattern) {
            double v1 = dx / fullX;
            double v2 = 1d - Math.pow(v1, 2 / 3d);
            double v3 = Math.pow(v2, 3 / 2d);
            return (int)(255 * v3);
        }
        return 0;
    }
    private static int verifyLighter(int v0_255) { //out:[100, 255]
        double k = (255 - 100) / 255d;
        return (int)(k * v0_255 + 100);
    }

    /*
    +----------------------------------->R
    |  \
    |     \
    |        \
    |           \
    |             \
    |                \
    |                   \
    |                       \
    |                          \
    |                             \
    |                                \
    G                                    B
    */
    public static Bitmap makeBmp_linear_rgb(int wid, int height) {
        Bitmap bmp = Bitmap.createBitmap(wid, height, Bitmap.Config.ARGB_8888);
        Canvas cv = new Canvas(bmp);
        Paint p = new Paint();

        int rPa = ParticleFW.rand(0, 9);
        int gPa = ParticleFW.rand(0, 9);
        int bPa = ParticleFW.rand(0, 9);
        int order = ParticleFW.rand(0, 5);
        Log.e(TAG, "rPa:" + rPa + ",  gPa:" + gPa + ", bPa:" + bPa + ", order:" + order);

        int deltaX, deltaY, deltaDia, color;
        double diagonal = Math.pow(wid * wid + height * height, 0.5);
        for (int px = 0; px < wid; px++) {
            for (int py = 0; py < height; py++) {
                deltaX = getValByPattern(rPa, px, wid);
                deltaY = getValByPattern(gPa, py, height);

                double dist = Math.pow(px * px + py * py, 0.5);
                deltaDia = getValByPattern(bPa, dist, diagonal);

                switch (order) {
                    case 0: color = Color.argb(0xFF, deltaX, deltaY, deltaDia); break; //xyd
                    case 1: color = Color.argb(0xFF, deltaX, deltaDia, deltaY); break; //xdy
                    case 2: color = Color.argb(0xFF, deltaDia, deltaX, deltaY); break; //dxy
                    case 3: color = Color.argb(0xFF, deltaDia, deltaY, deltaX); break; //dyx
                    case 4: color = Color.argb(0xFF, deltaY, deltaX, deltaDia); break; //yxd
                    case 5: color = Color.argb(0xFF, deltaY, deltaDia, deltaX); break; //ydx
                }
                color = Color.argb(0xFF, deltaX, deltaY, deltaDia);
                p.setColor(color);
                cv.drawPoint(px, py, p);
            }
        }
        mBmp = bmp;
        return bmp;
    }
    public static Bitmap subArt_linear_test(int wid, int height) {
        Bitmap bmp = Bitmap.createBitmap(wid, height, Bitmap.Config.ARGB_8888);
        Canvas cv = new Canvas(bmp);
        Paint p = new Paint();

        int deltaX, deltaY, deltaDia, color;
        double diagonal = Math.pow(wid * wid + height * height, 0.5);
        for (int px = 0; px < wid; px++) {
            for (int py = 0; py < height; py++) {
                double var0_1 = px / (double)wid; //[0, 1)
                double var0_2pi = var0_1 * 2 * Math.PI;
                double vsin = Math.sin(var0_2pi);//[-1, 1)
                double r = 255 * ((vsin + 1) / 2);

                color = Color.argb(0xFF, (int)r, 0, 0);
                p.setColor(color);
                cv.drawPoint(px, py, p);
            }
        }
        mBmp = bmp;
        return bmp;
    }


    public static Bitmap makeBmp_linear_hsl(int w, int h) {
        Bitmap bmp = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
        Canvas cv = new Canvas(bmp);
        Paint p = new Paint();

        int color;
        float rndH = ParticleFW.rand(0, 359);
        float rndL = ParticleFW.rand(42, 72) /  100f;

        int rndBE = ParticleFW.rand(0, 1);
        int rndXY = ParticleFW.rand(0, 1);
        
        for (int px = 0; px < w; px++) {
            for (int py = 0; py < h; py++) {
                int hue;
                if(1 == rndXY) {
                    int px360 = (int)(rndH + px * 360 / w);
                    px360 %= 360;
                    hue = px360;
                } else {
                    int py360 = (int)(rndH + py * 360 / h);
                    py360 %= 360;
                    if(1 == rndBE) hue = py360;
                    else hue = (360 - py360);
                }

                color = ParticleFW.hsla2argb(hue, 1f, rndL, 0xFF);
                p.setColor(color);
                cv.drawPoint(px, py, p);
            }
        }
        mBmp = bmp;
        return bmp;
    }

    /*
    |
    |
    |
    |
    |               r
    |             /
    |           /
    |         /
    |       /
    |     /
    |   /
    | / θ
    +----------------------------------->
    */
    void xy2polor(Coord in, Polor out) { //out:[-pi, pi]
        out.r = Math.pow(in.x *in.x + in.y * in.y, 0.5);
        out.theta = Math.atan2(in.y, in.x);
    }
    void polor2xy(Polor in, Coord out) { //out:[-pi, pi]
        out.x = (float)(in.r * Math.cos(in.theta));
        out.y = (float)(in.r * Math.sin(in.theta));
    }

    //in:bmp坐标系(左上为0,x向右,y向下)坐标, vPt:移动前原点,  out:基于vPt原点的原in坐标   y正方向反转+平移坐标轴
    void bmpCoord2VCoord(Coord in, Coord vPt, Coord out) {
        out.x = in.x - vPt.x;
        out.y = vPt.y - in.y;
    }
//    //in:vCoord坐标, vPt:bmp原点在v中的坐标,  out:bmp坐标
//    void v2BmpCoord(Coord in, Coord vPt, Coord out) {
//        out.x = in.x - vPt.x;
//        out.y = vPt.y - in.y;
//    }
    public Bitmap makeBmp_polar_1(int wid, int height) {
        Bitmap bmp = Bitmap.createBitmap(wid, height, Bitmap.Config.ARGB_8888);
        Canvas cv = new Canvas(bmp);
        Paint p = new Paint();

        Coord bC = new Coord();
        Coord vPt = new Coord(wid / 2, height / 2);
        Coord trans = new Coord();
        Polor pl = new Polor();
        int rnd = ParticleFW.rand(0, 5);
        int r = 0; int g = 0; int b = 0;
        for(int x = 0; x < wid; ++x) {
            for(int y = 0; y < height; ++y) {
               bC.x = x;
               bC.y = y;
                bmpCoord2VCoord(bC, vPt, trans);
                xy2polor(trans, pl);
                double t0_2pi = pl.theta;
                if(t0_2pi < 0) t0_2pi += (2 * Math.PI);

                int v = (int)(t0_2pi * 255 / (2 * Math.PI));
                switch (rnd) {
                    case 0: r = v;break;                    //100
                    case 1: {r = v; g = v;} break;          //110
                    case 2: {r = v; b = v;} break;          //101
                    case 3: {r = v; g = v; b = v;} break;   //111
                    case 4: g = v; break;                   //010
                    case 5: {g = v; b = v;} break;          //011
                    case 6: b = v; break;                   //001
                }
                p.setColor(Color.rgb(r, g, b));
                cv.drawPoint(x, y, p);
            }
        }
        mBmp = bmp;
        return bmp;
    }

    private double getMinDistance_3leaf(float vx, float vy, float radius, Coord nearestPt) {
        double minD = 10000000000000000d;
        for(int i = 0; i < 360; ++i) {
            double theta = i * Math.PI / 180;
            double ru = radius * Math.cos(3 * theta);
            double leaf3_x =  ru * Math.cos(theta);
            double leaf3_y =  ru * Math.sin(theta);
            double d = Math.pow((vx - leaf3_x) * (vx - leaf3_x) + (vy - leaf3_y) * (vy - leaf3_y), 0.5);
            if(d < minD) {
                minD = d;
                nearestPt.x = (float)leaf3_x;
                nearestPt.y = (float)leaf3_y;
            }
        }
        return minD;
    }
    public Bitmap subArt_polar_3leaf(int wid, int height) { //效率太低,待用path蒙版替代
        Bitmap bmp = Bitmap.createBitmap(wid, height, Bitmap.Config.ARGB_8888);
        Canvas cv = new Canvas(bmp);
        Paint p = new Paint();

        Coord bC = new Coord();
        Coord vPt = new Coord(wid / 2, height / 2);
        Coord trans = new Coord();
        Polor pl = new Polor();
        int rnd = 1;//ParticleFW.rand(0, 5);
        int r = 0; int g = 0; int b = 0;
        double dia = (wid / 2) * Math.pow(8, 0.5); //最大对角线
        Coord nearestPt = new Coord();
        for(int x = 0; x < wid; ++x) {
            for(int y = 0; y < height; ++y) {
                bC.x = x;
                bC.y = y;
                bmpCoord2VCoord(bC, vPt, trans);
                double d = getMinDistance_3leaf(trans.x, trans.y, wid / 2, nearestPt); //[0, dia)
                double leaf3_disPt = Math.pow(nearestPt.x * nearestPt.x + nearestPt.y * nearestPt.y, 0.5);
                if(leaf3_disPt > d) {
                    double weigth = d / (0.5 * wid / 2); //[0, ~~1)
                    r = (int)(weigth * 255);
                } else {
                    r = 0;
                    //double weigth = d / dia; //[0, ~~1)
                    //g = (int)(weigth * 255);
                }

//                double revd = dia - d; //[0, dia)
//                double scaled = revd / dia; //[0, 1)
//
//                xy2polor(trans, pl);
//                double the = Math.abs(pl.theta); //[0, pi]
//                int radColor = (int)(the * 255 / Math.PI);
//                //double v3 = Math.cos(the) * 255;
//
//                int v = (int)(scaled * 255);
//                switch (rnd) {
//                    case 0: r = v;break;                    //100
//                    case 1: {r = v; g = radColor;} break;          //110
//                    case 2: {r = v; b = v;} break;          //101
//                    case 3: {r = v; g = v; b = v;} break;   //111
//                    case 4: g = v; break;                   //010
//                    case 5: {g = v; b = v;} break;          //011
//                    case 6: b = v; break;                   //001
//                }
                p.setColor(Color.rgb(r, g, b));
                cv.drawPoint(x, y, p);
            }
        }
        mBmp = bmp;
        return bmp;
    }

    private Path makePath3leaf(float radius) {
        Path path = new Path();
        path.reset();
        path.moveTo(0, 0);
        for(int i = 0; i < 360; ++i) {
            double theta = i * Math.PI / 180;
            double ru = radius * Math.cos(3 * (theta + 60 * Math.PI / 180));
            double leaf3_x =  ru * Math.cos(theta);
            double leaf3_y =  ru * Math.sin(theta);
            path.lineTo((float) leaf3_x, (float) leaf3_y);
        }
        path.close();
        return path;
    }

    private int verifyPolar(Polor pl) {
        if(pl.theta <= 120 * Math.PI / 180) {
            pl.theta = Math.abs(pl.theta - 60 * Math.PI / 180);
            return 1;
        }
        if(pl.theta <= 240 * Math.PI / 180) {
            pl.theta = Math.abs(pl.theta - (60 + 120) * Math.PI / 180);
            return 2;
        }
        if(pl.theta <= 360 * Math.PI / 180) {
            pl.theta = Math.abs(pl.theta - (60 + 240) * Math.PI / 180);
            return 3;
        }
        return  3;
    }

    public Bitmap makeBmp_rose3(int wid, int height) {
        Bitmap bmp = Bitmap.createBitmap(wid, height, Bitmap.Config.ARGB_8888);
        Canvas cv = new Canvas(bmp);
        Paint p = new Paint();

        Path path = makePath3leaf(wid / 2);
        RectF rc = new RectF();
        path.computeBounds(rc, true);
        Region rg = new Region();
        rg.setPath(path, new Region((int)rc.left, (int)rc.top,(int)rc.right, (int)rc.bottom));

        Coord in = new Coord();
        Coord pt = new Coord(wid / 2, height / 2);
        Coord out = new Coord();
        Polor pl = new Polor();
        Polor plold = new Polor();
        int r = 0; int g = 0; int b = 0;
        for(int x = 0; x < wid; ++x) {
            for(int y = 0; y < height; ++y) {
                in.x = x; in.y = y;
                bmpCoord2VCoord(in, pt, out);
                xy2polor(out, plold);
                pl.theta = plold.theta; pl.r = plold.r;
                if(pl.theta < 0) pl.theta += 2 * Math.PI;
                int ret = verifyPolar(pl);
                float li = (float)(pl.theta / (60 * Math.PI / 180));

                double v1 = plold.theta + Math.PI; //[0, 2pi]
                double v2 = v1 / (2 * Math.PI);//[0, 1]
                int hue = 300;

                float s = 1f;
                if(rg.contains((int)out.x, (int)out.y)) {
                    hue += (int) (360 * v2 * v2);
                } else {
                    hue += (int) (360 * v2);
                }
                hue %= 360;

                int color = ParticleFW.hsla2argb(hue, s, li, 0xFF);
                p.setColor(color);
                cv.drawPoint(x, y, p);
            }
        }
        mBmp = bmp;
        return bmp;
    }

    double getInvoluteThetaByXY(int x, int y) {
        return 0;
    }
    public Bitmap makeBmp_involute2(int wid, int height) {
        Bitmap bmp = Bitmap.createBitmap(wid, height, Bitmap.Config.ARGB_8888);
        Canvas cv = new Canvas(bmp);
        Paint p = new Paint();

        float radius = wid / 2 / 10;
        for(int x = 0; x < wid; ++x) {
            for(int y = 0; y < height; ++y) {
                double theta = getInvoluteThetaByXY(x, y);

                int color = ParticleFW.hsla2argb((int)theta, 1f, 0.6f, 0xFF);
                p.setColor(color);
                cv.drawPoint(x, y, p);
            }
        }
        mBmp = bmp;
        return bmp;
    }
    public Bitmap makeBmp_involute(int wid, int height) {
        Bitmap bmp = Bitmap.createBitmap(wid, height, Bitmap.Config.ARGB_8888);
        Canvas cv = new Canvas(bmp);
        Paint p = new Paint();

        float radius = wid / 2 / 10;
        for(int ro = 0; ro < 360; ++ro) {
            for (int ag = 0; ag < 3 * 360; ++ag) {
                double theta = ag * Math.PI / 180;
                float x = (float) (radius * (Math.cos(theta) + Math.sin(theta) * theta));
                float y = (float) (radius * (Math.sin(theta) - Math.cos(theta) * theta));

                cv.save();
                cv.translate(wid / 2, height / 2);
                cv.rotate(ro);

                int color = ParticleFW.hsla2argb(ro, 1f, 0.6f, 0xFF);
                p.setColor(color);
                cv.drawPoint(x, y, p);
                cv.restore();
            }
        }
        mBmp = bmp;
        return bmp;
    }
//    subArt_linear_test
//    subArt_polar_3leaf

    protected void onDraw(Canvas canvas) {
        if(null != mBmp) canvas.drawBitmap(mBmp, 0, 0, null);
    }
}
